home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / Screen Rotator / main.c next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  9.7 KB  |  426 lines

  1. #if TARGET_CPU_68K && !TARGET_RT_MAC_CFM
  2.     #error Sorry Can't do that
  3. #endif
  4.  
  5. #include <MixedMode.h>
  6. #include <Appearance.h>
  7. #include <SpeechSynthesis.h>
  8.  
  9. #define kCapsLock    0x39
  10. #define    crsrBase    0x898
  11. #define kTimerDelay    0x20
  12.  
  13. #define kXOffset        0
  14. #define kYOffset        0
  15.  
  16. #define kScreenXShrink    0
  17. #define kScreenYShrink    0
  18.  
  19. typedef struct {
  20.     short            numPorts;
  21.     GrafPtr            ports [1];
  22. } **PortListHdl;
  23.  
  24. typedef struct {
  25.     QDGlobals            qd;                    // Storage for the QuickDraw globals
  26.     long                qdGlobalsPtr;        // A5 points to this place; it will contain a pointer to qd
  27. } QDStorage;
  28.  
  29. typedef struct {        // Time Manager information record
  30.     TMTask    tmTask;        // original and revised TMtask record
  31.     long     delay;
  32.     DeferredTask DTask;
  33. } TMInfo, *TMInfoPtr;
  34.  
  35. void RotateScreen(void);
  36. void InitScreenRotate(void);
  37. void InitDeferedTaskStruct(DeferredTask* dtask);
  38. Boolean isPressed(UInt16 key, UInt8*keymap);
  39. void ChangeAllPorts (Ptr oldBaseAddr, Ptr newBaseAddr);
  40. static long MySetA5 (void* value);
  41. pascal void MyTask(TMInfoPtr recPtr);
  42. void InitTimerStruct(void);
  43. void MyDeferredTask(DeferredTaskProcPtr theTask);
  44. void CheckScreenChange(void);
  45.  
  46.  
  47. Rect gMainBounds, gOriginalBounds;
  48. Ptr gScreenAddress, gBufferAddress;
  49. short gPixelSize , gScreenRowBytes;
  50.  
  51. GWorldPtr gMyGWorldPtr;    
  52.  
  53. QDStorage qds;
  54.  
  55.  
  56. TimerUPP gTimerProc;
  57. TMInfo gTask;
  58. Point gScreenOffset = { kYOffset, kXOffset };
  59. Point gScreenShrink = { kScreenYShrink, kScreenXShrink };
  60.  
  61. #define kScreenRotatorGestalt                    'SROT'
  62. #define kScreenOffsetGestalt                    'SOFF'
  63.  
  64. enum {
  65.     uppA5Info = kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(long)))
  66.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  67. };
  68.  
  69.  
  70. // Tell MetroWerks the procInfo for main
  71. ProcInfoType __procinfo =  kPascalStackBased;
  72. pascal void main(void)
  73. {
  74.     RoutineDescriptorPtr originaldesc, newdesc;
  75.     UInt32 size;
  76.     UInt16 index;
  77.     THz theZone;
  78.     OSErr err;
  79.  
  80.     // get globals
  81. //    EnterCodeResource();
  82.     // detach ourselves
  83.     DetachResource(Get1Resource('INIT', 0));
  84.  
  85.     // make sure we are in the system heap
  86.     theZone = GetZone();
  87.     SetZone(SystemZone());
  88.  
  89.     InitScreenRotate();
  90.  
  91.     gTimerProc = NewTimerProc(MyTask);
  92.  
  93.     InitTimerStruct();
  94.     InitDeferedTaskStruct(&gTask.DTask);
  95.  
  96.     err = NewGestaltValue(kScreenRotatorGestalt, (UInt32) &gTask.delay);
  97.     err = NewGestaltValue(kScreenOffsetGestalt, (UInt32) &gScreenOffset);
  98.  
  99.     InsTime((QElemPtr) &gTask.tmTask);                    // install the info record
  100.     PrimeTime((QElemPtr) &gTask.tmTask, gTask.delay);    // activate the info record
  101.  
  102.     // restore to original heap
  103.     SetZone(theZone);
  104.     // restore globals
  105. //    ExitCodeResource();
  106. }
  107.  
  108.  
  109. void RotateScreen(void)
  110. {
  111.     long height = gMainBounds.bottom - gMainBounds.top; 
  112.     long width = gMainBounds.right - gMainBounds.left; 
  113.     Ptr src_start = gBufferAddress;
  114.     Ptr dst_start = (gScreenAddress + (height * gScreenRowBytes));
  115.     Ptr src, dst;
  116.     long row, col;
  117.  
  118.     dst_start += ((gScreenOffset.v >>1) * gScreenRowBytes);
  119.     dst_start -= ((gScreenOffset.h >>1) * gPixelSize);
  120.  
  121.     for (row = 0; row < height; row++) {
  122.         BlockMoveData(src_start, dst_start, gScreenRowBytes);
  123.         src_start += gScreenRowBytes;
  124.         dst_start -= gScreenRowBytes;
  125.     }
  126.     return;
  127.  
  128.     switch (gPixelSize) {
  129.         case 8:
  130.             for (row = 0; row < height; row++) {
  131.                 src = src_start;
  132.                 dst = dst_start;
  133.                 for (col = 0; col < width; col++) {
  134.                     *((UInt8*)dst) = *((UInt8*)src);
  135.                     dst -= sizeof(UInt8);
  136.                     src += sizeof(UInt8);
  137.                 }
  138.                 src_start += gScreenRowBytes;
  139.                 dst_start -= gScreenRowBytes;
  140.             }
  141.             break;
  142.  
  143.         case 16:
  144.             for (row = 0; row < height; row++) {
  145.                 src = src_start;
  146.                 dst = dst_start;
  147.                 for (col = 0; col < width; col++) {
  148.                     *((UInt16*)dst) = *((UInt16*)src);
  149.                     dst -= sizeof(UInt16);
  150.                     src += sizeof(UInt16);
  151.                 }
  152.                 src_start += gScreenRowBytes;
  153.                 dst_start -= gScreenRowBytes;
  154.             }
  155.             break;
  156.  
  157.         case 24:
  158.             for (row = 0; row < height; row++) {
  159.                 src = src_start;
  160.                 dst = dst_start;
  161.                 for (col = 0; col < width; col++) {
  162.                     *((UInt16*)dst) = *((UInt16*)src);
  163.                     dst -= sizeof(UInt16);
  164.                     src += sizeof(UInt16);
  165.                     *((UInt8*)dst) = *((UInt8*)src);
  166.                     dst -= sizeof(UInt8);
  167.                     src += sizeof(UInt8);
  168.                 }
  169.                 src_start += gScreenRowBytes;
  170.                 dst_start -= gScreenRowBytes;
  171.             }
  172.             break;
  173.  
  174.  
  175.         case 32:
  176.             for (row = 0; row < height; row++) {
  177.                 src = src_start;
  178.                 dst = dst_start;
  179.                 for (col = 0; col < width; col++) {
  180.                     *((UInt32*)dst) = *((UInt32*)src);
  181.                     dst -= sizeof(UInt32);
  182.                     src += sizeof(UInt32);
  183.                 }
  184.                 src_start += gScreenRowBytes;
  185.                 dst_start -= gScreenRowBytes;
  186.             }
  187.             break;
  188.  
  189.         default:
  190.             break;
  191.     }
  192. }
  193.  
  194.  
  195. void InitScreenRotate(void)
  196. {
  197.     PixMapHandle dst_pixmap, main_pixmap;
  198.     GDHandle mygdHandle, maindevice;
  199.     THz theZone;
  200.     CGrafPtr cwMgrPort;
  201.     GrafPtr    wMgrPort;
  202.     Rect tempBounds = {0,0,1,1}, originalScreen;
  203.     long bytesNeeded, oldA5;
  204.     short wMgrRowBytes, cwMgrRowBytes;
  205.     OSErr err;
  206.  
  207.     theZone = GetZone();
  208.     SetZone(SystemZone());
  209.  
  210.     oldA5 = MySetA5(&qds.qdGlobalsPtr);                        // Tell A5 to point to the end of the fake QD Globals
  211.     InitGraf(&qds.qd.thePort);                                // Initialize the fake QD Globals
  212.  
  213.     maindevice = LMGetMainDevice();    
  214.     main_pixmap = (**maindevice).gdPMap;
  215.     gOriginalBounds =  (**maindevice).gdRect;
  216.     gPixelSize = (*main_pixmap)->pixelSize;
  217.  
  218.     
  219.     
  220.     gScreenRowBytes = ((**main_pixmap).rowBytes & 0x3FFF);
  221.     gMainBounds = gOriginalBounds;
  222.  
  223.     originalScreen = gMainBounds;
  224.     gMainBounds.bottom -= gScreenShrink.v;
  225.     gMainBounds.right -= gScreenShrink.h;
  226.     LockPixels(main_pixmap);
  227.  
  228.     (**maindevice).gdRect = gMainBounds;
  229.     gScreenAddress = GetPixBaseAddr(main_pixmap);
  230.     gMyGWorldPtr = nil;
  231.     err = NewGWorld(&gMyGWorldPtr, (*main_pixmap)->pixelSize, &tempBounds, nil, nil, 0);
  232.     if (err) {
  233.         SysBeep(1);
  234.         (**maindevice).gdRect = gOriginalBounds;
  235.         SetZone(theZone);
  236.         MySetA5((void*)oldA5);
  237.         return;
  238.     }
  239.     
  240.     bytesNeeded = (originalScreen.bottom - originalScreen.top)  * gScreenRowBytes;
  241.     gBufferAddress = NewPtrSysClear(bytesNeeded);
  242.     if (!gBufferAddress) {
  243.         SysBeep(1);
  244.         SysBeep(1);
  245.         (**maindevice).gdRect = gOriginalBounds;
  246.         SetZone(theZone);
  247.         MySetA5((void*)oldA5);
  248.         return;
  249.     }
  250.  
  251.     BlockMoveData(gScreenAddress, gBufferAddress, bytesNeeded);
  252.  
  253.     dst_pixmap = GetGWorldPixMap(gMyGWorldPtr);
  254.     LockPixels (dst_pixmap);
  255.  
  256.     (**dst_pixmap).baseAddr = gBufferAddress;
  257.     (**dst_pixmap).rowBytes = (**main_pixmap).rowBytes;
  258.     (**dst_pixmap).bounds = gMainBounds;
  259.  
  260.     InitFonts();
  261.     InitWindows();
  262.     InitMenus();
  263.     InitDialogs(nil);
  264.         
  265.     /* Fake out cursor drawing */
  266.     *((Ptr*)crsrBase) = gBufferAddress;
  267.  
  268.     /* Fake out main GDevice */
  269.     (**(**maindevice).gdPMap).baseAddr = gBufferAddress;
  270.     
  271.     GDeviceChanged (maindevice); // ••? quinn doesn't know ••
  272.  
  273.     /* Fake out B&W windows */    
  274.     wMgrPort = LMGetWMgrPort();
  275.     wMgrRowBytes = wMgrPort -> portBits.rowBytes;
  276.     wMgrPort -> portBits.baseAddr = gBufferAddress;
  277.  
  278.     /* Fake out color windows */
  279.     cwMgrPort = *(CGrafPtr*)0xd2c;
  280.     cwMgrRowBytes = (**(cwMgrPort -> portPixMap)).rowBytes;
  281.     (**cwMgrPort -> portPixMap).baseAddr = gBufferAddress;
  282.  
  283.     /* Fake out QuickDraw */
  284.     LMSetScrnBase(gBufferAddress);
  285.  
  286.     ChangeAllPorts (gScreenAddress, gBufferAddress);// ••? quinn doesn't know - but he's doubtful ••
  287.     MySetA5((void*)oldA5);
  288.     SetZone(theZone);
  289. }
  290.  
  291. void ChangeAllPorts (Ptr oldBaseAddr, Ptr newBaseAddr)
  292. {        
  293.     PortListHdl        ports = *((PortListHdl*) 0x0000d66);
  294.     int i;
  295.     for (i = 0; i < (**ports).numPorts; ++i) {
  296.     
  297.         if ((**ports).ports [i] -> portBits.rowBytes & 0xC000) {
  298.                 
  299.             CGrafPtr        port = (CGrafPtr) ((**ports).ports [i]);
  300.             
  301.             if (GetPixBaseAddr (port -> portPixMap) == oldBaseAddr)
  302.                 (**(port -> portPixMap)).baseAddr = newBaseAddr;
  303.     
  304.         } else {
  305.         
  306.             GrafPtr            port = ((**ports).ports [i]);
  307.  
  308.             if (port -> portBits.baseAddr == oldBaseAddr)
  309.                 port -> portBits.baseAddr = newBaseAddr;
  310.         
  311.         }
  312.     }
  313. }
  314.  
  315.  
  316. void CheckScreenChange(void)
  317. {
  318.     
  319.     Rect originalScreen;
  320.     PixMapHandle dst_pixmap;
  321.     GDHandle maindevice = LMGetMainDevice();    
  322.     PixMapHandle main_pixmap = (**maindevice).gdPMap;
  323.     Rect newRect =  (**maindevice).gdRect;
  324.     short newsize = (*main_pixmap)->pixelSize;
  325.     short newRowBytes = ((**main_pixmap).rowBytes & 0x3FFF);
  326.  
  327.  
  328.     if (
  329.         (newRect.right != gMainBounds.right || newRect.bottom != gMainBounds.bottom) ||
  330.         (newsize  != gPixelSize) ||
  331.         newRowBytes != gScreenRowBytes) {
  332.  
  333.  
  334.         gMainBounds = newRect;
  335.         originalScreen = gMainBounds;
  336.         gMainBounds.bottom -= gScreenShrink.v;
  337.         gMainBounds.right -= gScreenShrink.h;
  338.         LockPixels(main_pixmap);
  339.  
  340.         (**maindevice).gdRect = gMainBounds;
  341.  
  342.         gPixelSize = newsize;
  343.         gScreenRowBytes = newRowBytes;
  344.  
  345.         dst_pixmap = GetGWorldPixMap(gMyGWorldPtr);
  346.         LockPixels (dst_pixmap);
  347.  
  348.         (**dst_pixmap).baseAddr = gBufferAddress;
  349.         (**dst_pixmap).rowBytes = (**main_pixmap).rowBytes;
  350.         (**dst_pixmap).bounds = gMainBounds;
  351.         
  352.         GDeviceChanged(maindevice);
  353.     }
  354. }
  355.  
  356.  
  357. //////////////////// isPressed ////////////////////
  358. Boolean isPressed(UInt16 key, UInt8*keymap)
  359. {
  360.     return ((keymap[key>>3] >> (key & 7) ) & 1);            // return true if a given key is pressed
  361. }
  362.  
  363. static long MySetA5 (void* value)
  364. {
  365.     short hex [7] = {
  366.             0x4e56,
  367.             0x0000,
  368.             0x202e,
  369.             0x0008,
  370.             0xc18d,
  371.             0x4e5e,
  372.             0x4e75
  373.         };
  374.  
  375.     UniversalProcPtr    upp;
  376.     long oldA5;
  377.  
  378. //    MakeDataExecutable (&hex, 14);
  379.  
  380.     upp = NewRoutineDescriptor ((ProcPtr) &hex, uppA5Info, kM68kISA);
  381.     if (!upp)
  382.         DebugStr ("\pDONT EVEN THINK ABOUT IT!");
  383.  
  384.     oldA5 = CallUniversalProc (upp, uppA5Info, value);
  385.  
  386.     return oldA5;
  387. }
  388.  
  389. pascal void MyTask(TMInfoPtr recPtr)
  390. {
  391.     OSErr err;
  392.     err = DTInstall(&(recPtr->DTask));
  393. }
  394.  
  395. void InitTimerStruct(void)
  396. {
  397.     gTask.tmTask.tmAddr = gTimerProc;
  398.     gTask.tmTask.tmWakeUp = 0;                    // initialize tmWakeUp
  399.     gTask.tmTask.tmReserved = 0;                // initialize tmReserved
  400.     gTask.delay = kTimerDelay;
  401. }
  402.  
  403. void InitDeferedTaskStruct(DeferredTask* dtask)
  404. {
  405.     dtask->qLink = 0;
  406.     dtask->qType = dtQType;
  407.     dtask->dtFlags = 0;
  408.     dtask->dtAddr = NewDeferredTaskProc(MyDeferredTask);
  409.     dtask->dtParam = 0;
  410.     dtask->dtReserved = 0;
  411. }
  412.  
  413. void MyDeferredTask(DeferredTaskProcPtr theTask)
  414. {
  415. //    EnterCodeResource();
  416.  
  417.     if (gScreenAddress != nil && gBufferAddress != nil) {
  418.         CheckScreenChange();
  419.         RotateScreen();
  420.         PrimeTime( (QElemPtr) &gTask, gTask.delay);
  421.     }
  422. //    ExitCodeResource();
  423. }
  424.  
  425.  
  426.